/*
 * Copyright (C) 2012-2013  Romain DUBOIS
 * 
 * This file is part of NeMoS - Network and Modular Software
 * 
 * NeMoS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * NeMoS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with NeMoS.  If not, see <http://www.gnu.org/licenses/>.
 */
package nemos.util.log;

import nemos.util.i18n.ITranslator;
import nemos.util.i18n.NemosTranslator;
import nemos.util.log.internal.BundleLogger;

import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;

/**
 * NemosLogger : The NeMoS logger class.
 * 
 * <p>
 * This class redirect log messages to the OSGi {@link LogService} if available.
 * It relies on the {@link NemosTranslator} to translate and format messages.
 * </p>
 * 
 * @author Romain DUBOIS
 */
public class NemosLogger {

    /** The current service */
    private ServiceReference<?> mServiceRef;
    /** The bundle logger */
    private final BundleLogger mLogger;

    /**
     * Constructor
     * 
     * @param pClass
     *            The logging class
     */
    public NemosLogger(final Class<?> pClass) {
        this(FrameworkUtil.getBundle(pClass));
    }

    /**
     * Constructor
     * 
     * @param pBundle
     *            The bundle to log from
     */
    public NemosLogger(final Bundle pBundle) {
        super();

        mLogger = BundleLogger.getLogger(pBundle);
    }

    /**
     * Get the logger translator.
     * 
     * @return The translator
     */
    public ITranslator getTranslator() {
        return mLogger.getTranslator();
    }

    /**
     * Log a debug message for a service.
     * 
     * @param pRef
     *            The concerned service reference
     * @param pMessage
     *            The localized message reference
     * @param pMsgParameters
     *            The message parameters
     */
    public void debug(final ServiceReference<?> pRef, final String pMessage,
            final Object... pMsgParameters) {
        log(pRef, LogService.LOG_DEBUG, pMessage, null, pMsgParameters);
    }

    /**
     * Log a debug message for a service and with an exception.
     * 
     * @param pRef
     *            The concerned service reference
     * @param pMessage
     *            The localized message reference
     * @param pException
     *            The exception
     * @param pMsgParameters
     *            The message parameters
     */
    public void debug(final ServiceReference<?> pRef, final String pMessage,
            final Throwable pException, final Object... pMsgParameters) {
        log(pRef, LogService.LOG_DEBUG, pMessage, pException, pMsgParameters);
    }

    /**
     * Log a debug message.
     * 
     * @param pMessage
     *            The localized message reference
     * @param pMsgParameters
     *            The message parameters
     */
    public void debug(final String pMessage, final Object... pMsgParameters) {
        log(mServiceRef, LogService.LOG_DEBUG, pMessage, null, pMsgParameters);
    }

    /**
     * Log a debug message with an exception.
     * 
     * @param pMessage
     *            The localized message reference
     * @param pException
     *            The exception
     * @param pMsgParameters
     *            The message parameters
     */
    public void debug(final String pMessage, final Throwable pException,
            final Object... pMsgParameters) {
        log(mServiceRef, LogService.LOG_DEBUG, pMessage, pException, pMsgParameters);
    }

    /**
     * Log an error message for a service.
     * 
     * @param pRef
     *            The concerned service reference
     * @param pMessage
     *            The localized message reference
     * @param pMsgParameters
     *            The message parameters
     */
    public void error(final ServiceReference<?> pRef, final String pMessage,
            final Object... pMsgParameters) {
        log(pRef, LogService.LOG_ERROR, pMessage, null, pMsgParameters);
    }

    /**
     * Log an error message for a service and with an exception.
     * 
     * @param pRef
     *            The concerned service reference
     * @param pMessage
     *            The localized message reference
     * @param pException
     *            The exception
     * @param pMsgParameters
     *            The message parameters
     */
    public void error(final ServiceReference<?> pRef, final String pMessage,
            final Throwable pException, final Object... pMsgParameters) {
        log(pRef, LogService.LOG_ERROR, pMessage, pException, pMsgParameters);
    }

    /**
     * Log an error message.
     * 
     * @param pMessage
     *            The localized message reference
     * @param pMsgParameters
     *            The message parameters
     */
    public void error(final String pMessage, final Object... pMsgParameters) {
        log(mServiceRef, LogService.LOG_ERROR, pMessage, null, pMsgParameters);
    }

    /**
     * Log an error message with an exception.
     * 
     * @param pMessage
     *            The localized message reference
     * @param pException
     *            The exception
     * @param pMsgParameters
     *            The message parameters
     */
    public void error(final String pMessage, final Throwable pException,
            final Object... pMsgParameters) {
        log(mServiceRef, LogService.LOG_ERROR, pMessage, pException, pMsgParameters);
    }

    /**
     * Log an information message for a service.
     * 
     * @param pRef
     *            The concerned service reference
     * @param pMessage
     *            The localized message reference
     * @param pMsgParameters
     *            The message parameters
     */
    public void info(final ServiceReference<?> pRef, final String pMessage,
            final Object... pMsgParameters) {
        log(pRef, LogService.LOG_INFO, pMessage, null, pMsgParameters);
    }

    /**
     * Log an information message for a service and with an exception.
     * 
     * @param pRef
     *            The concerned service reference
     * @param pMessage
     *            The localized message reference
     * @param pException
     *            The exception
     * @param pMsgParameters
     *            The message parameters
     */
    public void info(final ServiceReference<?> pRef, final String pMessage,
            final Throwable pException, final Object... pMsgParameters) {
        log(pRef, LogService.LOG_INFO, pMessage, pException, pMsgParameters);
    }

    /**
     * Log an information message.
     * 
     * @param pMessage
     *            The localized message reference
     * @param pMsgParameters
     *            The message parameters
     */
    public void info(final String pMessage, final Object... pMsgParameters) {
        log(mServiceRef, LogService.LOG_INFO, pMessage, null, pMsgParameters);
    }

    /**
     * Log an information message with an exception.
     * 
     * @param pMessage
     *            The localized message reference
     * @param pException
     *            The exception
     * @param pMsgParameters
     *            The message parameters
     */
    public void info(final String pMessage, final Throwable pException,
            final Object... pMsgParameters) {
        log(mServiceRef, LogService.LOG_INFO, pMessage, pException, pMsgParameters);
    }

    /**
     * Set a service reference to use in each following logs which do not have a
     * service reference.
     * 
     * @param pReference
     *            The service reference to use in log
     */
    public void setServiceReference(final ServiceReference<?> pReference) {
        mServiceRef = pReference;
    }

    /**
     * Log a warning message for a service.
     * 
     * @param pRef
     *            The concerned service reference
     * @param pMessage
     *            The localized message reference
     * @param pMsgParameters
     *            The message parameters
     */
    public void warn(final ServiceReference<?> pRef, final String pMessage,
            final Object... pMsgParameters) {
        log(pRef, LogService.LOG_WARNING, pMessage, null, pMsgParameters);
    }

    /**
     * Log a warning message for a service and with an exception.
     * 
     * @param pRef
     *            The concerned service reference
     * @param pMessage
     *            The localized message reference
     * @param pException
     *            The exception
     * @param pMsgParameters
     *            The message parameters
     */
    public void warn(final ServiceReference<?> pRef, final String pMessage,
            final Throwable pException, final Object... pMsgParameters) {
        log(pRef, LogService.LOG_WARNING, pMessage, pException, pMsgParameters);
    }

    /**
     * Log a warning message.
     * 
     * @param pMessage
     *            The localized message reference
     * @param pMsgParameters
     *            The message parameters
     */
    public void warn(final String pMessage, final Object... pMsgParameters) {
        log(mServiceRef, LogService.LOG_WARNING, pMessage, null, pMsgParameters);
    }

    /**
     * Log a warning message with an exception.
     * 
     * @param pMessage
     *            The localized message reference
     * @param pException
     *            The exception
     * @param pMsgParameters
     *            The message parameters
     */
    public void warn(final String pMessage, final Throwable pException,
            final Object... pMsgParameters) {
        log(mServiceRef, LogService.LOG_WARNING, pMessage, pException, pMsgParameters);
    }

    /**
     * Log a message for a service.
     * 
     * @param pRef
     *            The concerned service reference
     * @param pLogLevel
     *            The log level
     * @param pMessage
     *            The localized message reference
     * @param pMsgParameters
     *            The message parameters
     */
    public void log(final ServiceReference<?> pRef, final int pLogLevel, final String pMessage,
            final Object... pMsgParameters) {
        log(pRef, pLogLevel, pMessage, null, pMsgParameters);
    }

    /**
     * Log a message for a service and with an exception.
     * 
     * @param pRef
     *            The logging service reference
     * @param pLogLevel
     *            The log level
     * @param pMessage
     *            The message
     * @param pException
     *            The exception
     * @param pMsgParameters
     *            The message parameters
     */
    public void log(final ServiceReference<?> pRef, final int pLogLevel, final String pMessage,
            final Throwable pException, final Object... pMsgParameters) {
        mLogger.log(getTranslator(), pRef, pLogLevel, pMessage, pException, pMsgParameters);
    }

    /**
     * Log a warning message.
     * 
     * @param pLogLevel
     *            The log level
     * @param pMessage
     *            The localized message reference
     * @param pMsgParameters
     *            The message parameters
     */
    public void log(final int pLogLevel, final String pMessage, final Object... pMsgParameters) {
        log(mServiceRef, pLogLevel, pMessage, null, pMsgParameters);
    }

    /**
     * Log a warning message with an exception.
     * 
     * @param pLogLevel
     *            The log level
     * @param pMessage
     *            The localized message reference
     * @param pException
     *            The exception
     * @param pMsgParameters
     *            The message parameters
     */
    public void log(final int pLogLevel, final String pMessage, final Throwable pException,
            final Object... pMsgParameters) {
        log(mServiceRef, pLogLevel, pMessage, pException, pMsgParameters);
    }
}
